#ifndef QUERYCALLBACK_H__
#define QUERYCALLBACK_H__

namespace engine
{

	class QueryResult;
	class QueryResultSet;

	//////////////////////////////////////////////////////////////////////////
	class IQueryCallback
	{
	public:
		virtual ~IQueryCallback() {}
		virtual void execute() = 0;

	public:
		IQueryCallback() : mResultSet(0) {}

		void setResultSet(QueryResultSet* resultSet)
		{
			mResultSet = resultSet;
		}

	protected:
		QueryResultSet* mResultSet;
	};

	//////////////////////////////////////////////////////////////////////////
	template<class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void, typename ParamType5 = void, typename ParamType6 = void>
	class QueryCallback : public IQueryCallback
	{
	private:
		typedef void (Class::*Method)(QueryResultSet*, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6);
		Class* mObject;
		Method mMethod;
		ParamType1 mParam1;
		ParamType2 mParam2;
		ParamType3 mParam3;
		ParamType4 mParam4;
		ParamType5 mParam5;
		ParamType6 mParam6;

		void call()
		{
			(mObject->*mMethod)(mResultSet, mParam1, mParam2, mParam3, mParam4, mParam5, mParam6);
		}

	public:
		QueryCallback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4, ParamType5 param5, ParamType6 param6)
			: mObject(object), mMethod(method), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(param4), mParam5(param5), mParam6(param6)
		{
		}

		virtual void execute()
		{
			call();
			delete mResultSet;
		}
	};

	//////////////////////////////////////////////////////////////////////////
	template<class Class, typename ParamType1, typename ParamType2, typename ParamType3, typename ParamType4, typename ParamType5>
	class QueryCallback<Class, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> : public IQueryCallback
	{
	private:
		typedef void (Class::*Method)(QueryResultSet*, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5);
		Class* mObject;
		Method mMethod;
		ParamType1 mParam1;
		ParamType2 mParam2;
		ParamType3 mParam3;
		ParamType4 mParam4;
		ParamType5 mParam5;

		void call()
		{
			(mObject->*mMethod)(mResultSet, mParam1, mParam2, mParam3, mParam4, mParam5);
		}

	public:
		QueryCallback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4, ParamType5 param5)
			: mObject(object), mMethod(method), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(param4), mParam5(param5)
		{
		}

		void execute()
		{
			call();
			delete mResultSet;
		}
	};

	//////////////////////////////////////////////////////////////////////////
	template<class Class, typename ParamType1, typename ParamType2, typename ParamType3, typename ParamType4>
	class QueryCallback<Class, ParamType1, ParamType2, ParamType3, ParamType4> : public IQueryCallback
	{
	private:
		typedef void (Class::*Method)(QueryResultSet*, ParamType1, ParamType2, ParamType3, ParamType4);
		Class* mObject;
		Method mMethod;
		ParamType1 mParam1;
		ParamType2 mParam2;
		ParamType3 mParam3;
		ParamType4 mParam4;

		void call()
		{
			(mObject->*mMethod)(mResultSet, mParam1, mParam2, mParam3, mParam4);
		}

	public:
		QueryCallback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4)
			: mObject(object), mMethod(method), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(param4)
		{
		}

		void execute()
		{
			call();
			delete mResultSet;
		}
	};

	//////////////////////////////////////////////////////////////////////////
	template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
	class QueryCallback<Class, ParamType1, ParamType2, ParamType3> : public IQueryCallback
	{
	private:
		typedef void (Class::*Method)(QueryResultSet*, ParamType1, ParamType2, ParamType3);
		Class* mObject;
		Method mMethod;
		ParamType1 mParam1;
		ParamType2 mParam2;
		ParamType3 mParam3;

		void call()
		{
			(mObject->*mMethod)(mResultSet, mParam1, mParam2, mParam3);
		}

	public:
		QueryCallback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3)
			: mObject(object), mMethod(method), mParam1(param1), mParam2(param2), mParam3(param3)
		{
		}

		void execute()
		{
			call();
			delete mResultSet;
		}
	};

	//////////////////////////////////////////////////////////////////////////
	template<class Class, typename ParamType1, typename ParamType2>
	class QueryCallback<Class, ParamType1, ParamType2> : public IQueryCallback
	{
	private:
		typedef void (Class::*Method)(QueryResultSet*, ParamType1, ParamType2);
		Class* mObject;
		Method mMethod;
		ParamType1 mParam1;
		ParamType2 mParam2;

		void call()
		{
			(mObject->*mMethod)(mResultSet, mParam1, mParam2);
		}

	public:
		QueryCallback(Class *object, Method method, ParamType1 param1, ParamType2 param2)
			: mObject(object), mMethod(method), mParam1(param1), mParam2(param2)
		{
		}

		void execute()
		{
			call();
			delete mResultSet;
		}
	};

	//////////////////////////////////////////////////////////////////////////
	template<class Class, typename ParamType1>
	class QueryCallback<Class, ParamType1> : public IQueryCallback
	{
	private:
		typedef void (Class::*Method)(QueryResultSet*, ParamType1);
		Class* mObject;
		Method mMethod;
		ParamType1 mParam1;

		void call()
		{
			(mObject->*mMethod)(mResultSet, mParam1);
		}

	public:
		QueryCallback(Class *object, Method method, ParamType1 param1)
			: mObject(object), mMethod(method), mParam1(param1)
		{
		}

		void execute()
		{
			call();
			delete mResultSet;
		}
	};

	//////////////////////////////////////////////////////////////////////////
	template<class Class>
	class QueryCallback<Class> : public IQueryCallback
	{
	private:
		typedef void (Class::*Method)(QueryResultSet*);
		Class* mObject;
		Method mMethod;

		void call()
		{
			(mObject->*mMethod)(mResultSet);
		}

	public:
		QueryCallback(Class *object, Method method)
			: mObject(object), mMethod(method)
		{
		}

		void execute()
		{
			call();
			delete mResultSet;
		}
	};
}

#endif
